#include "type.h"
#include "hal.h"


uint8_t io_in8(uint16_t port){
    uint8_t data;
    asm volatile ("inb %1, %0" : "=a" (data) : "Nd" (port));
    return data;
}

uint16_t io_in16(uint16_t port){
    uint16_t data;
    asm volatile ("inw %1, %0" : "=a" (data) : "Nd" (port));
    return data;
}

uint32_t io_in32(uint16_t port){
    uint32_t data;
    asm volatile ("inl %1, %0" : "=a" (data) : "Nd" (port));
    return data;
}

void io_out8(uint16_t port, uint8_t msg){
    asm volatile ("outb %0, %1" : : "a" (msg), "Nd" (port));
}

void io_out16(uint16_t port, uint16_t msg){
    asm volatile ("outw %0, %1" : : "a" (msg), "Nd" (port));
}

void io_out32(uint16_t port, uint32_t msg){
    asm volatile ("outl %0, %1" : : "a" (msg), "Nd" (port));
}

int32_t io_printf(const char* string){
    if(io_printf_mode == 0){
        for(int32_t i=0;string[i]!='\0'&&i<=MAX_STRING;i++){
            putc_serial(string[i]);
        }
    }
}

int32_t io_scanf(int32_t max_size, char* str){
    if(io_scanf_mode == 0){
        for(int32_t i=0;i<max_size-1;i++){
            str[i]=gets_serial();
            if(str[i]=='\n') break;
        }
        str[max_size-1]='\0';
    }
}

void io_hlt(){
    __asm__ __volatile__("hlt");
}

/*  串口    */
void init_serial(){
    // 初始化串口，设置波特率
    io_out8(0x3F8 + 1, 0x00);
    io_out8(0x3F8 + 3, 0x80);
    io_out8(0x3F8 + 0, 0x03);
    io_out8(0x3F8 + 1, 0x00);
    io_out8(0x3F8 + 3, 0x03);
    io_out8(0x3F8 + 2, 0xC7);
    io_out8(0x3F8 + 4, 0x0B);
}
void putc_serial(char c) {
    // 等待串口
    while ((io_in8(0x3F8 + 5) & 0x20) == 0);
    // 发送字符到串口
    io_out8(0x3F8, c);
}

char gets_serial() {
    uint8_t result;  // 定义 result 变量
    __asm__ __volatile__ (
        "check_rx_buffer:        \n\t"
        "movw $0x3FD, %%dx       \n\t"  // 串口状态端口
        "inb %%dx, %%al          \n\t"  // 读取状态
        "testb $0x01, %%al       \n\t"  // 检查数据是否就绪
        "jz check_rx_buffer      \n\t"  // 未就绪则循环等待
        "movw $0x3F8, %%dx       \n\t"  // 串口数据端口
        "inb %%dx, %%al          \n\t"  // 读取数据到 AL
        : "=a" (result)                // 输出：AL 寄存器 → result
        :                              // 无输入操作数
        : "dx", "memory"               // 破坏列表：DX 寄存器和内存
    );
    return result;
}
